package storageManager;

import java.util.ArrayList;
import java.util.Collections;

public class IndexPage extends Page{
	public TableRecord tableRecord;
	public String maxKeyValue;
	public int sizeOfTheKeyValue;
	public int sizeOfAnIndexRecord;
	public int numberOfAvailableRecords;
	public ArrayList<IndexRecord> indexRecords;
	public IndexPage(TableRecord record){
		this.tableRecord = record;
		this.sizeOfTheKeyValue = record.getFieldSizes().get(0);
		this.sizeOfAnIndexRecord = record.getSizeOfAnIndexRecord();
	}
	public String getMaxKeyValue() {
		return maxKeyValue;
	}
	public void setMaxKeyValue(String keyValue) {
		this.maxKeyValue = keyValue;
	}
	public int getNumberOfAvailableRecords() {
		return numberOfAvailableRecords;
	}
	public void setNumberOfAvailableRecords(int numberOfAvailableRecords) {
		this.numberOfAvailableRecords = numberOfAvailableRecords;
	}
	public ArrayList<IndexRecord> getIndexRecords() {
		return indexRecords;
	}
	public void setIndexRecords(ArrayList<IndexRecord> records) {
		this.indexRecords = records;
	}
	public void updatePageHeader(){//This method updates the page header according to the current state of the page.
		numberOfAvailableRecords = tableRecord.getNumberOfTotalIndexRecord()-indexRecords.size();
		if(indexRecords.size()==0){
			maxKeyValue = maxString();//If there is no record in the page, than it updates the maxKeyValue to maxString
		}else{
			maxKeyValue = indexRecords.get(indexRecords.size()-1).getKeyValue();//Otherwise updates it to the last element of the record list
		}
	}
	public void sortThePage(){//Sorts the record and updates the page header
		Collections.sort(indexRecords);
		updatePageHeader();
	}
	public IndexRecord getLastIndexRecord(){//Gets the last record of the page
		IndexRecord theLastRecord = indexRecords.get(indexRecords.size()-1);
		this.indexRecords.remove(indexRecords.size()-1);
		updatePageHeader();
		return theLastRecord;
	}
	public IndexRecord getFirstIndexRecord(){//Gets the first record of the page
		IndexRecord theFirstRecord = indexRecords.get(0);
		this.indexRecords.remove(0);
		updatePageHeader();
		return theFirstRecord;
	}
	public void addIndexRecord(IndexRecord record){//Adds an index record and sorts the page
		indexRecords.add(record);
		sortThePage();
	}
	public boolean hasAvailableSpace(){//Returns true if the page has available record space
		if(this.indexRecords.size()<tableRecord.getNumberOfTotalIndexRecord()){
			return true;
		}
		return false;
	}
	public IndexRecord removeRecord(String keyValue){//Removes the record with the given keyValue from the list
		IndexRecord record = findTheRecord(keyValue);
		this.indexRecords.remove(record);
		updatePageHeader();
		return record;
	}
	public IndexRecord findTheRecord(String keyValue){//Finds and returns the record with the given keyValue
		for(IndexRecord record : this.indexRecords){
			if(record.getKeyValue().equals(keyValue)){
				return record;
			}
		}
		return null;
	}
	public boolean isInPage(String keyValue){//Returns true if there is a record with the given keyValue
		for(IndexRecord record:indexRecords){
			if(keyValue.equalsIgnoreCase(record.getKeyValue())){
				return true;
			}
		}
		return false;
	}
	public ArrayList<IndexRecord> smallerThan(String keyValue){//Returns the index records that has smaller keyValues than the given keyValue
		ArrayList<IndexRecord> result = new ArrayList<IndexRecord>();
		if(indexRecords.size()>0){
			IndexRecord theRecord = indexRecords.get(0);
			int i=0;
			while(Tools.comparator(keyValue, theRecord.getKeyValue())>=0){
				result.add(theRecord);
				i++;
				try{
					theRecord = indexRecords.get(i);
				}catch(Exception e){
					break;
				}
			}
		}
		return result;
	}
	public byte[] toByte(){//Parse the page object to a byte array
		byte[] result = new byte[512];
		System.arraycopy(Tools.stringToByte(maxKeyValue,sizeOfTheKeyValue), 0, result, 0, sizeOfTheKeyValue);
		result[sizeOfTheKeyValue] = (byte) numberOfAvailableRecords;
		for(int i=0;i<indexRecords.size();i++){
			IndexRecord record = indexRecords.get(i);
			byte[] bytes =record.toByte(sizeOfTheKeyValue);
			System.arraycopy(bytes, 0, result, sizeOfTheKeyValue+1+i*sizeOfAnIndexRecord, sizeOfAnIndexRecord);
		}
		return result;
	}
	public String maxString(){//Decides the maxString according to the type of the keyValue
		byte[] max = new byte[sizeOfTheKeyValue];
		for(int i=0; i<sizeOfTheKeyValue; i++){
			max[i] = (byte) 127;
		}
		return Tools.byteToString(max);
	}
}
